from rest_framework import serializers
from host import models
from hippo_api.utils.check_ssh import valid_ssh
from hippo_api.libs.ssh import SSH
from hippo_api.utils.handle_key import AppSetting


class HostCategoryModelSeiralizer(serializers.ModelSerializer):
    class Meta:
        model = models.HostCategory
        fields = ['id', 'name']


class HostModelSerializers(serializers.ModelSerializer):
    # 显示分类名称
    category_name = serializers.CharField(source='category.name', read_only=True)
    # 数据model 并没有password字段，所以需要定义，然后校验，之后重写create方法，在save入库前pop掉
    password = serializers.CharField(max_length=32, write_only=True)

    class Meta:
        model = models.Host
        # category是一个外建字段的ID，要想获取name，还得处理 category_name
        fields = ['id', 'category', 'category_name', 'hostname', 'ip_addr', 'port', 'desc', 'username', 'password']

        extra_kwargs = {
            'category': {'write_only': True},
        }

    # 校验用户提交来的数据，是否能够连接到某台主机
    def validate(self, attrs):
        ip_addr = attrs.get('ip_addr')
        port = attrs.get('port')
        username = attrs.get('username')
        password = attrs.get('password')

        ret = valid_ssh(ip_addr, port, username, password)
        if not ret:
            raise serializers.ValidationError('参数校验失败，请检查输入的内容')
        return attrs

    # 数据入库
    def create(self, validated_data):
        ip_addr = validated_data.get('ip_addr')
        port = validated_data.get('port')
        username = validated_data.get('username')
        password = validated_data.get('password')

        # 添加host记录，如果第一次添加host记录，那么需要我们生成全局的公钥和私钥
        # 创建公私钥之前，我们先看看之前是否已经创建过公私钥了
        _cli = SSH(ip_addr, port, username, password=str(password))
        try:
            # AppSetting自定义工具类 获取数据库中的密钥对
            private_key = AppSetting.get('private_key')
            public_key = AppSetting.get('public_key')
        except KeyError:
            # 如果之前没有创建过，那么就创建公钥和私钥
            private_key, public_key = _cli.generate_key()
            # AppSetting自定义工具类 将公钥和私钥保存到数据库中
            AppSetting.set('private_key', private_key, 'ssh private key')
            AppSetting.set('public_key', public_key, 'ssh public key')

        # 将公钥上传到服务器上保存
        _cli.add_public_key(public_key)

        # 剔除密码字段，保存host记录
        validated_data.pop('password')
        new_host_obj = models.Host.objects.create(
            **validated_data
        )
        return new_host_obj
